package com.javaDemo.ti;

import lombok.SneakyThrows;

import java.util.concurrent.Semaphore;

/**
 * @ClassName: HHO
 * @Auther: csy   https://leetcode-cn.com/problems/building-h2o/solution/semaphor-cyclicbarrier-zhi-guan-shi-xian-by-luca-z/
 * @Date: 2021/3/8 17:29
 * @Description:
 */
public class HHO {
    private Semaphore h = new Semaphore(2);
    private Semaphore o = new Semaphore(0);


    public static void main(String[] args) {

        for(int i=0;i<100;i++) {
            gen();
        }
    }


    private static void gen() {
        Semaphore semaphoreH = new Semaphore(2);
        Semaphore semaphoreO = new Semaphore(1);
        // CyclicBarrier cyclicBarrier=  new CyclicBarrier(3);
            new Thread(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    semaphoreH.acquire();
                    System.out.println("h");
                    // releaseHydrogen.run() outputs "H". Do not change or remove this line.
                    // try {
                    //     cyclicBarrier.await();
                    // } catch (BrokenBarrierException e) {
                    //     e.printStackTrace();
                    // }
                }
            }).start();
            new Thread(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    semaphoreO.acquire();
                    System.out.println("o");
                    // releaseOxygen.run() outputs "O". Do not change or remove this line.
                    // try {
                    //     cyclicBarrier.await();
                    // } catch (BrokenBarrierException e) {
                    //     e.printStackTrace();
                    // }
                }
            }).start();
        }
    Object lock = new Object();
    // H元素的数量
    volatile int hNum = 0;



    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
        synchronized(lock) {
            // 只要H元素数量等于2，就要卡住
            while (hNum == 2) {
                lock.notifyAll();
                lock.wait();
            }
            releaseHydrogen.run();
            hNum++;
            // 唤醒其他线程
            lock.notifyAll();
        }

    }

    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        synchronized(lock) {
            // 只要H元素数量不等于2，就要卡住
            while (hNum != 2) {
                lock.notifyAll();
                lock.wait();
            }
            releaseOxygen.run();
            // 进入下一轮
            hNum = 0;
            // 唤醒其他线程
            lock.notifyAll();
        }

    }

}
